package customConnectionPool;
import lombok.extern.slf4j.Slf4j;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicIntegerArray;

class TestConnectionPool {

    public static void main(String[] args) throws Exception {
        CustomConnectionPool pool = new CustomConnectionPool(5);
        for (int i = 0; i < 20; i++) {
            new Thread(() -> {
                MyConnection conn = pool.getConnection(Thread.currentThread().getName());
                try {
                    TimeUnit.SECONDS.sleep(1);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                pool.freeConnection(conn,Thread.currentThread().getName());
            }).start();
        }
    }

}

@Slf4j
class CustomConnectionPool {

    // 1. 连接池大小
    private final Integer PoolSize;

    private AtomicIntegerArray atomicConnStatusArray;

    private MyConnection[] connectionArray;

    //创建连接池
    public CustomConnectionPool(Integer PoolSize) throws Exception {

        this.PoolSize = PoolSize;

        atomicConnStatusArray = new AtomicIntegerArray(new int[PoolSize]);

        this.connectionArray = new MyConnection[PoolSize];

        if(PoolSize <= 0){
            throw new Exception("创建连接池发生异常！");
        }

        for (int i = 0; i < PoolSize; i++) {
            MyConnection myConnectionItem =
                    new MyConnection("连接池：" + String.valueOf(i) + "号");
            //往连接池数组和标记位数组中存放元素
            connectionArray[i] = myConnectionItem;
        }

    }


    //获取链接
    public MyConnection getConnection(String threadName){

        while (true){
            for (int i = 0; i < PoolSize; i++) {
                if(atomicConnStatusArray.get(i) == 0){
                    if(atomicConnStatusArray.compareAndSet(i,0,1)){
                        log.info(threadName + connectionArray[i].getConnectionName() + "已被获取返回连接 ----in");
                        return connectionArray[i];
                    }
                }
            }

            //当连接池连接用完后,阻塞等待
            synchronized (this){
                try {
                    log.debug("wait...");
                    this.wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }


    }


    //释放链接
    public void freeConnection(MyConnection connection,String threadName){

        while (true){
            for (int i = 0; i < PoolSize; i++) {
                if(connectionArray[i] == connection){
                    log.info(threadName + connectionArray[i].getConnectionName() + "退回池中 ----back");
                        atomicConnStatusArray.set(i,0);
                        //当连接池使用完后,重新归还到连接池
                        synchronized (this){
                            this.notifyAll();
                        }
                }
            }
            break;
        }
    }



}

/*
空类,用于模拟Connection类
*/
class MyConnection{

    private String connectionName;

    public MyConnection(String connectionName) {
        this.connectionName = connectionName;
    }

    public String getConnectionName() {
        return connectionName;
    }

    public void setConnectionName(String connectionName) {
        this.connectionName = connectionName;
    }
}